package org.uim.cricket.storage;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.uim.cricket.storage.deserialize.impl.XMLAnalyzerDeserializer;

public class DBQueries {

	static {
		System.setProperty("org.apache.commons.logging.Log",
        "org.apache.commons.logging.impl.NoOpLog");
	}
	
	/**
	 * @param args 
	 * 		argument #1 = source directory of analyzer files
	 * 		argument #2 = -sd:{yes/no} Indicates whether find analyzer files inside subdirectories. (optional)
	 * 		argument #3 = source query file
	 * 		argument #4 = -q:{yes/no} run queries (optional) (default: no)
	 */
	public static void main(String[] args) throws Exception {
		Dlogger.debug("Initializing Cricket storage application...");
		
		if (args == null) {
			Dlogger.error(" - Input arguments can't be null!");
			Dlogger.error("Terminating application.");
			throw new Exception("Input arguments can't be null!");
		}
		
		InputArgumentParser argParser = null;
		
		try {
			
			Dlogger.debug(" Loading properties...");
			StorageProperties.load();
			
			Dlogger.debug(" Parsing arguments...");
			argParser = new InputArgumentParser(args);
			argParser.setRunQueries(StorageProperties.getBoolValue("run.queries"));
			
			argParser.parse();
			
		} catch (Exception ex) {
			Dlogger.error("Error occured!", ex);
			Dlogger.debug("Terminating application.");
			return;
		}
		
		File srcQuery = new File(argParser.getSourceQueryFile());
		if (!srcQuery.exists()) {
			srcQuery.createNewFile();
			Dlogger.debug(" Source query file is not found, but created a new one.");
		}
		
		if (argParser.isQueryExecuteOnly()) {
			
			Dlogger.debug(" Understood: Query executes only.");
			FileQueryStringFetcher qexe = new FileQueryStringFetcher(argParser.getSourceQueryFile());
			QueryExecutable exable = new DefaultQueryExecutor();
			

			Dlogger.debug("   Using query executor as [" + exable.getClass().getName() + "]");
			try {
				
				qexe.executeQueries(exable);
				Dlogger.debug(" Completed executing queries!");
				Dlogger.debug("Application successfully completed.");
				
			} catch (Exception ex) {
				Dlogger.error(" Terminated with an error!", ex);
				System.exit(1);
			}
			
			System.exit(0);
		}
		
		List<String> files = getAllAnalyzeFiles(argParser.getAnalyzerDir(), argParser.isSubDirs());
		if (files == null || files.size() == 0) {
			
			Dlogger.debug(" No analyzer files found!");
			
		} else {
			
			String cFile = null;
			try {
				
				if (argParser.getLimit() < 0) {
					for (int i=0; i<files.size(); i++) {
						cFile = files.get(i);
						
						Dlogger.debug(" Parsing analyzer file: " + cFile);
						XMLAnalyzerDeserializer xmlanal = new XMLAnalyzerDeserializer(cFile);
						Storage data = xmlanal.deserialize();
						
						Dlogger.debug("   - Generating queries...");
						DBExecutor dbexec = new DBExecutor(data, new FileQueryAppender(argParser.getSourceQueryFile())); 
						dbexec.execute();
						
					}
				} else {
					
					Dlogger.debug(" Only maximum of " + argParser.getLimit() + " files will be parsed!");
					int n = Math.min(argParser.getLimit(), analFiles.size());
					
					for (int i=0; i<n; i++) {
						cFile = files.get(i);
						
						Dlogger.debug(" Parsing analyzer file: " + cFile);
						XMLAnalyzerDeserializer xmlanal = new XMLAnalyzerDeserializer(cFile);
						Storage data = xmlanal.deserialize();
						
						Dlogger.debug("   - Generating queries...");
						DBExecutor dbexec = new DBExecutor(data, new FileQueryAppender(argParser.getSourceQueryFile())); 
						dbexec.execute();
						
					}
				}
				
				
			} catch (Exception ex) {
				
				Dlogger.error(" Error in analyzing file '"+ cFile +"'!", ex);
				
			}
			
			
		}
		
		if (argParser.isRunQueries()) {
			
			Dlogger.debug(" Queries are preparing to execute...");
			FileQueryStringFetcher qexe = new FileQueryStringFetcher(argParser.getSourceQueryFile());
			QueryExecutable exable = new DefaultQueryExecutor();
			

			Dlogger.debug("   Using query executor as [" + exable.getClass().getName() + "]");
			try {
				
				qexe.executeQueries(exable);
				Dlogger.debug(" Completed executing queries!");
				
			} catch (Exception ex) {
				Dlogger.error(" Terminated with an error!", ex);
				System.exit(1);
			}

		}
		
		Dlogger.debug("Application successfully completed.");
		System.exit(0);
	}

	private static List<String> analFiles = null;
	
	private static List<String> getAllAnalyzeFiles(String sourceDir, boolean inSubDirs) {
		analFiles = new ArrayList<String>();
		File folder = new File(sourceDir);
		
		if (!folder.exists()) return analFiles;
		if (folder.isFile()) {
			analFiles.add(sourceDir);
			return analFiles;
		}
		
		if (!inSubDirs) {
			
			for (File f : folder.listFiles()) {
				if (f.isFile()) {
					analFiles.add(f.getAbsolutePath());
				}
			}
			
		} else {
			scanFolder(folder);
		}
		
		return analFiles;
	}
	
	private static void scanFolder(File folder) {
		if (!folder.isDirectory()) {
			analFiles.add(folder.getAbsolutePath());
		} else {
			
			for (File f : folder.listFiles()) {
				if (f.isDirectory()) 
					scanFolder(f);
				else
					analFiles.add(f.getAbsolutePath());
			}
			
		}
	}
	
}
